﻿namespace DCHealthCheck.MvcWeb.Classes.ViewModels {

    #region Usings
    using DCHealthCheck.DomainModel;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Caching;
    using System.Web.Mvc;
    using System.Web.Mvc.Html;
    #endregion

    public abstract class BaseViewModel : IBaseViewModel {

        #region Members
        public string ActionName { get; set; }

        public string ControllerName { get; set; }

        public bool DisplayDownloadLink { get; set; }

        public int UtcOffsetMinutes { get; set; }

        #region Query string filters
        public string ADSite { get; set; }
        public string DCName { get; set; }
        public string Domain { get; set; }
        public Guid DomainControllerId { get; set; }
        public string OSVersion { get; set; }
        public string ProcessExecutable { get; set; }
        public Guid SystemInfoId { get; set; }

        #region Date/Start/End dates
        /// <summary>
        /// Used to query for a specific full date+time in this format: "yyyy-MM-ddTHH:mm:ss.FFFFFFF"
        /// </summary>
        public DateTime Date { get; set; }
        private DateTime DefaultStartDateOffset = DateTime.UtcNow.Date.AddDays(-30);
        public DateTime MostRecentResultDateTime { get; set; }
        public DateTime? EndDate {
            get {
                return endDate;
            }
            set {
                if (value.HasValue) {
                    endDate = value.Value.Date;
                }
                else {
                    endDate = null;
                }
            }
        }
        private DateTime? endDate;
        public DateTime? StartDate {
            get {
                return startDate;
            }
            set {
                if (value.HasValue) {
                    startDate = value.Value.Date;
                }
                else {
                    startDate = null;
                }
            }
        }
        private DateTime? startDate;
        #endregion
        #endregion

        #region Control SelectList collections
        public List<SelectListItem> ADSiteSelectListItems { get; private set; }
        public List<SelectListItem> DCNameSelectListItems { get; private set; }
        public List<SelectListItem> DomainSelectListItems { get; private set; }
        public List<SelectListItem> OSVersionSelectListItems { get; private set; }
        public List<SelectListItem> ProcessExecutableSelectListItems { get; private set; }
        #endregion

        #region Sorting properties
        public System.Web.Helpers.SortDirection? CurrentSortDirection { get; set; }
        public string SortColumn { get; set; }
        #endregion

        #region Paging control counts
        public int DisplayIntervalStart { get; protected set; }
        public int DisplayIntervalEnd { get; protected set; }
        public int DisplayTotalResults { get; set; }
        public int? SkipCount { get; set; }
        public int? TakeCount { get; set; }
        #endregion
        #endregion

        #region Constructor
        public BaseViewModel() {
            //Global.DefaultLog.DebugFormat("[ThreadId: {0}] {1}", Thread.CurrentThread.ManagedThreadId, Extensions.CurrentMethodName());

            if (HttpContext.Current != null) {
                if (HttpContext.Current.Session != null) {
                    if (HttpContext.Current.Session["UTCOffsetMinutes"] != null) {
                        this.UtcOffsetMinutes = Convert.ToInt32(HttpContext.Current.Session["UTCOffsetMinutes"]);
                    }
                }

                if (HttpContext.Current.Request != null) {
                    if (HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] != null) {
                        this.ControllerName = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
                    }
                    if (HttpContext.Current.Request.RequestContext.RouteData.Values["action"] != null) {
                        this.ActionName = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString();
                    }
                }
            }

            this.ADSiteSelectListItems = new List<SelectListItem>();
            this.DomainSelectListItems = new List<SelectListItem>();
            this.DCNameSelectListItems = new List<SelectListItem>();
            this.OSVersionSelectListItems = new List<SelectListItem>();
            this.ProcessExecutableSelectListItems = new List<SelectListItem>();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Generates the display text for the page count relative to the current collection.
        /// I.e., Results: 400 - 471 of 471
        /// </summary>
        /// <param name="collectionCount">
        /// The total amount of items in the collection if paging were not in use.  Typically determined by
        /// calling .Count() on IQueryable, or .Count on Lists.
        /// </param>
        public void GetPageCounts() {
            this.GetPageCounts(this.DisplayTotalResults);
        }
        public void GetPageCounts(int collectionCount) {
            //Global.DefaultLog.DebugFormat("[ThreadId: {0}] {1}", Thread.CurrentThread.ManagedThreadId, Extensions.CurrentMethodName());

            this.DisplayIntervalStart = (collectionCount == 0) ? 0 : this.SkipCount.Value + 1;

            if (collectionCount >= this.TakeCount) {
                this.DisplayIntervalEnd = this.SkipCount.Value + this.TakeCount.Value;
                if (this.DisplayIntervalEnd > collectionCount) {
                    this.DisplayIntervalEnd = collectionCount;
                }
            }
            else {
                this.DisplayIntervalEnd = this.SkipCount.Value + collectionCount;
            }
        }

        /// <summary>
        /// Models are initialized after they are constructed and the ModelBinder has populated them with values from the
        /// Request.QueryString, Request.Form, etc
        /// </summary>
        public virtual void Initialize() {
            //Global.DefaultLog.DebugFormat("[ThreadId: {0}] {1}", Thread.CurrentThread.ManagedThreadId, Extensions.CurrentMethodName());

            if (this.DCName != null) this.DCName = this.DCName.Trim();
            if (this.Domain != null) this.Domain = this.Domain.Trim();
            if (this.SortColumn != null) this.SortColumn = this.SortColumn.Trim();
            if (!this.SkipCount.HasValue) this.SkipCount = 0;
            if (!this.TakeCount.HasValue || (this.TakeCount == 0)) this.TakeCount = 100;
            if (!this.CurrentSortDirection.HasValue) {
                if (!string.IsNullOrWhiteSpace(this.SortColumn) && string.Equals(this.SortColumn, "Date", StringComparison.OrdinalIgnoreCase)) {
                    this.CurrentSortDirection = System.Web.Helpers.SortDirection.Descending;
                }
                else {
                    this.CurrentSortDirection = System.Web.Helpers.SortDirection.Ascending;
                }
            }

            this.SetStartDateAndEndDate();
        }

        /// <summary>
        /// Helper method to determine if a drop down list select list item should be present or
        /// filtered out due to existing filters
        /// </summary>
        public bool IsNotFilteredDomainController(DomainController domainController) {
            bool isNotFiltered = true;

            isNotFiltered &= !string.IsNullOrWhiteSpace(this.ADSite) ? this.ADSite == domainController.ADSite : true;
            isNotFiltered &= !string.IsNullOrWhiteSpace(this.Domain) ? this.Domain == domainController.NetbiosDomain : true;
            isNotFiltered &= !string.IsNullOrWhiteSpace(this.OSVersion) ? this.OSVersion == domainController.OSVersion : true;
            isNotFiltered &= !string.IsNullOrWhiteSpace(this.DCName) ? this.DCName == domainController.SamAccountName : true;

            return isNotFiltered;
        }

        /// <summary>
        /// Sets the StartDate and EndDate of the ViewModel filters
        /// </summary>
        /// <param name="startDateOffset"></param>
        public virtual void SetStartDateAndEndDate() {
            if (this.Date != DateTime.MinValue) {
                this.StartDate = this.Date;
                this.EndDate = this.Date;
            }
            else if (this.SystemInfoId == Guid.Empty) {

                if (!this.EndDate.HasValue || (this.EndDate == DateTime.MinValue)) {
                    this.EndDate = DateTime.UtcNow.Date.AddDays(1);
                }

                if (!this.StartDate.HasValue || (this.StartDate == DateTime.MinValue)) {
                    this.StartDate = this.DefaultStartDateOffset;
                }
            }
            else {
                this.StartDate = null;
                this.EndDate = null;
            }
        }

        #region GetSortColumnLink methods
        /// <summary>
        /// Helper method to create the links for Next and Sort columns
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="linkTitle">The tooltip</param>
        /// <param name="skipCount"></param>
        /// <param name="defaultSortDirection">Ascending or Descending.  Descending is typically used for numeric or date values.</param>
        /// <param name="sortColumn">The string name of the column that will be used in the SQL query for OrderBy</param>
        public MvcHtmlString GetSortColumnLink(HtmlHelper htmlHelper, string linkText, string linkTitle) {
            return this.GetSortColumnLink(this.ActionName, this.ControllerName, htmlHelper, linkText, linkTitle, this.SortColumn, this.DisplayIntervalEnd);
        }

        /// <summary>
        /// Sort by a different column
        /// </summary>
        public MvcHtmlString GetSortColumnLink(HtmlHelper htmlHelper, string linkText, string linkTitle, string sortColumn) {
            return this.GetSortColumnLink(this.ActionName, this.ControllerName, htmlHelper, linkText, linkTitle, sortColumn, null, this.CurrentSortDirection);
        }
        public MvcHtmlString GetSortColumnLink(string action, string controller, HtmlHelper htmlHelper, string linkText, string linkTitle, string sortColumn) {
            return this.GetSortColumnLink(action, controller, htmlHelper, linkText, linkTitle, sortColumn, null, System.Web.Helpers.SortDirection.Ascending);
        }
        public MvcHtmlString GetSortColumnLink(string action, string controller, HtmlHelper htmlHelper, string linkText, string linkTitle, string sortColumn, int? skipCount) {
            return this.GetSortColumnLink(action, controller, htmlHelper, linkText, linkTitle, sortColumn, skipCount, null);
        }

        /// <summary>
        /// Helper method to create the links for Next and Sort columns
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="linkText"></param>
        /// <param name="linkTitle">The tooltip</param>
        /// <param name="skipCount"></param>
        /// <param name="defaultSortDirection">Ascending or Descending.  Descending is typically used for numeric or date values.</param>
        /// <param name="sortColumn">The string name of the column that will be used in the SQL query for OrderBy</param>
        /// <returns></returns> 
        public MvcHtmlString GetSortColumnLink(
                    string action,
                    string controller,
                    HtmlHelper htmlHelper,
                    string linkText,
                    string linkTitle,
                    string sortColumn,
                    int? skipCount,
                    System.Web.Helpers.SortDirection? defaultSortDirection) {
            System.Web.Helpers.SortDirection sortDirection = this.CurrentSortDirection.HasValue ? this.CurrentSortDirection.Value : System.Web.Helpers.SortDirection.Ascending;

            #region Determine SortDirection, based on existing direction and default SortDirection
            if (defaultSortDirection.HasValue) {
                if (defaultSortDirection == System.Web.Helpers.SortDirection.Ascending) {
                    if ((this.SortColumn == sortColumn) && (this.CurrentSortDirection == System.Web.Helpers.SortDirection.Ascending)) {
                        sortDirection = System.Web.Helpers.SortDirection.Descending;
                    }
                    else {
                        sortDirection = System.Web.Helpers.SortDirection.Ascending;
                    }
                }
                else {
                    if ((this.SortColumn == sortColumn) && (this.CurrentSortDirection == System.Web.Helpers.SortDirection.Descending)) {
                        sortDirection = System.Web.Helpers.SortDirection.Ascending;
                    }
                    else {
                        sortDirection = System.Web.Helpers.SortDirection.Descending;
                    }
                }
            }
            #endregion

            System.Web.Routing.RouteValueDictionary htmlAttributes = new System.Web.Routing.RouteValueDictionary();
            htmlAttributes.Add("title", linkTitle);
            string onClickText = string.Format("spinblock();$('#hiddenSortColumn').val('{0}');$('#hiddenCurrentSortDirection').val('{1}');searchForm.submit();return false;", sortColumn, sortDirection);
            htmlAttributes.Add("onclick", onClickText);

            if (string.Equals(this.SortColumn, sortColumn, StringComparison.OrdinalIgnoreCase) && !string.Equals(linkText, "Next", StringComparison.OrdinalIgnoreCase)) {
                htmlAttributes.Add("style", "color:maroon");
            }

            MvcHtmlString link = htmlHelper.ActionLink(linkText, action, controller, null, htmlAttributes);
            return link;
        }
        #endregion
        #endregion

    }
}